# -*- coding: utf-8 -*-

"""
Description: 图片操作
"""

from PIL import Image, ImageDraw, ImageFont
import textwrap
import numpy as np
import os


def load_img(image_path: str) -> Image.Image:
    """
    加载图片，并转换为RGBA模式
    """
    img = Image.open(image_path)

    # 转换为RGBA模式以处理透明度
    if img.mode != "RGBA":
        img = img.convert("RGBA")
    return img


def save_img(img: Image.Image, output_path: str):
    """
    保存图片
    """
    img.save(output_path)


def get_background_color(image: Image.Image) -> tuple:
    """获取图片背景色，返回颜色元组
    Args:
        img: 图片

    Returns:
        tuple: 颜色元组
    """

    # 获取所有像素数据
    pixels = np.array(image.getdata())

    # 统计每个颜色出现的频率
    unique_colors, counts = np.unique(pixels, axis=0, return_counts=True)

    # 排除透明像素 (alpha == 0)
    non_transparent = counts[unique_colors[:, 3] != 0]
    colors = unique_colors[unique_colors[:, 3] != 0]

    # 如果有数据，取最多的那个颜色（最常见颜色）
    if len(colors) > 0:
        most_common_color = colors[np.argmax(non_transparent)]
        return tuple(most_common_color)
    else:
        return None


def resize_to_square_with_black_bg(
    img: Image.Image, size: int = 512, background_color: tuple = (0, 0, 0, 255)
):
    """
    调整图片为正方形，填充背景色

    Args:
        img: 输入图片
        size: 正方形边长（默认512px）
        background_color: 背景色（默认黑色）
    """

    # 创建黑色背景的正方形画布
    square_img = Image.new("RGBA", (size, size), background_color)

    # 计算缩放比例，保持宽高比
    img_width, img_height = img.size
    scale = min(size / img_width, size / img_height)

    # 计算新的尺寸
    new_width = int(img_width * scale)
    new_height = int(img_height * scale)

    # 调整图片大小
    img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

    # 计算居中位置
    x = (size - new_width) // 2
    y = (size - new_height) // 2

    # 将调整后的图片粘贴到黑色背景上
    square_img.paste(img_resized, (x, y), img_resized)

    # 转换为RGB模式并保存
    square_img = square_img.convert("RGBA")
    return square_img


def no_conversion_overlay(
    image1: Image.Image,
    image2: Image.Image,
    position: tuple = (0, 0),
    alpha: float = 1.0,
):
    """
    图片加框，并返回加框后的图片
    """

    # 使用numpy进行高效处理
    img1_array = np.array(image1)
    img2_array = np.array(image2)

    # 调整透明度
    if alpha < 1.0:
        img2_array[:, :, 3] = (img2_array[:, :, 3] * alpha).astype(np.uint8)

    # 计算叠加位置
    x, y = position
    h2, w2 = img2_array.shape[:2]
    h1, w1 = img1_array.shape[:2]

    # 边界检查
    if x + w2 > w1:
        w2 = w1 - x
        img2_array = img2_array[:h2, :w2]
    if y + h2 > h1:
        h2 = h1 - y
        img2_array = img2_array[:h2, :w2]

    # 执行alpha混合
    if x >= 0 and y >= 0 and w2 > 0 and h2 > 0:
        alpha_overlay = img2_array[:, :, 3:4] / 255.0
        alpha_background = 1.0 - alpha_overlay

        # RGB通道混合
        img1_array[y : y + h2, x : x + w2, :3] = (
            alpha_overlay * img2_array[:, :, :3]
            + alpha_background * img1_array[y : y + h2, x : x + w2, :3]
        ).astype(np.uint8)

        # Alpha通道混合
        img1_array[y : y + h2, x : x + w2, 3:4] = np.maximum(
            img1_array[y : y + h2, x : x + w2, 3:4], img2_array[:, :, 3:4]
        )

    # 转换回PIL图像
    return Image.fromarray(img1_array, "RGBA")


def add_text_auto_fit_layered(
    image: Image.Image,
    text: str,
    region: tuple = (50, 50, 300, 200),
    max_font_size: int = 50,
    min_font_size: int = 10,
    font_color: tuple = (255, 255, 255),
    align: str = "",
    valign: str = "middle",
    padding: int = 4,
):
    """
    使用图层合成的方式添加文字，避免模糊
    """
    # 检查字体文件是否存在
    font_path = "MiSans-Heavy.ttf"
    if not os.path.exists(font_path):
        raise FileNotFoundError(f"字体文件 {font_path} 不存在")

    # 打开原图
    base_image = image

    # 创建文字图层，使用与原图相同的尺寸和模式
    if base_image.mode == "RGBA":
        text_layer = Image.new("RGBA", base_image.size, (0, 0, 0, 0))
    else:
        text_layer = Image.new("RGBA", base_image.size, (0, 0, 0, 0))
        base_image = base_image.convert("RGBA")

    draw = ImageDraw.Draw(text_layer)

    x1, y1, x2, y2 = region
    available_width = x2 - x1 - 2 * padding
    available_height = y2 - y1 - 2 * padding

    # 寻找最佳字体大小
    best_font_size = min_font_size
    best_lines = []

    for font_size in range(max_font_size, min_font_size - 1, -1):
        font = ImageFont.truetype(font_path, font_size)

        # 改进的换行逻辑
        lines = []
        for paragraph in text.split("\n"):
            if not paragraph.strip():
                lines.append("")
                continue

            # 使用实际字符宽度进行换行
            words = paragraph.split()
            current_line = ""

            for word in words:
                test_line = current_line + (" " if current_line else "") + word
                bbox = draw.textbbox((0, 0), test_line, font=font)
                line_width = bbox[2] - bbox[0]

                if line_width <= available_width:
                    current_line = test_line
                else:
                    # 如果当前行不为空，先保存当前行
                    if current_line:
                        lines.append(current_line)
                        current_line = word
                    else:
                        # 单个词太长，强制换行
                        if word:
                            # 检查单个词是否超长
                            word_bbox = draw.textbbox((0, 0), word, font=font)
                            word_width = word_bbox[2] - word_bbox[0]

                            if word_width > available_width:
                                # 按字符强制换行
                                for i, char in enumerate(word):
                                    test_char_line = current_line + char
                                    char_bbox = draw.textbbox(
                                        (0, 0), test_char_line, font=font
                                    )
                                    char_width = char_bbox[2] - char_bbox[0]

                                    if char_width <= available_width:
                                        current_line = test_char_line
                                    else:
                                        if current_line:
                                            lines.append(current_line)
                                        current_line = char
                            else:
                                current_line = word

            # 添加最后一行
            if current_line:
                lines.append(current_line)

        # 计算总高度
        line_height = font_size + max(3, font_size // 8)
        non_empty_lines = [l for l in lines if l.strip()]
        total_height = len(non_empty_lines) * line_height

        # 检查是否适合高度
        if total_height <= available_height:
            # 再次验证每行宽度（双重检查）
            fits = True
            for line in lines:
                if line.strip():
                    line_bbox = draw.textbbox((0, 0), line, font=font)
                    if (line_bbox[2] - line_bbox[0]) > available_width:
                        fits = False
                        break

            if fits:
                best_font_size = font_size
                best_lines = lines
                break

    # 使用最佳字体大小绘制
    final_font = ImageFont.truetype(font_path, best_font_size)

    line_height = best_font_size + max(3, best_font_size // 8)
    non_empty_lines = [l for l in best_lines if l.strip()]
    total_text_height = len(non_empty_lines) * line_height - max(3, best_font_size // 8)

    # 计算起始位置
    if valign == "middle":
        start_y = y1 + padding + (available_height - total_text_height) // 2
    elif valign == "bottom":
        start_y = y2 - padding - total_text_height
    else:
        start_y = y1 + padding

    # 绘制文字到图层
    current_y = start_y
    for line in best_lines:
        if not line.strip():
            continue

        # 计算水平位置
        line_bbox = draw.textbbox((0, 0), line, font=final_font)
        line_width = line_bbox[2] - line_bbox[0]

        if align == "center":
            line_x = x1 + padding + (available_width - line_width) // 2
        elif align == "right":
            line_x = x2 - padding - line_width
        else:
            line_x = x1 + padding

        # 绘制文字（带完全不透明的alpha）
        draw.text((line_x, current_y), line, fill=font_color + (255,), font=final_font)
        current_y += line_height

    # 合成图层
    result = Image.alpha_composite(base_image, text_layer)

    # 根据原图格式保存
    original_format = image.format
    if original_format == "PNG":
        return result
    else:
        return result.convert("RGB")


# result = add_text_auto_fit_layered(
#     "upload.jpg",
#     "result.jpg",
#     "移液管，100ml，独立纸塑袋包装，灭菌",
#     region=(350, 700, 790, 790),
#     max_font_size=40,
#     min_font_size=12,
# )
# print("文字添加完成")


# get_background_color("download/801011.jpg")
# get_background_color("download/801011.jpg")


def process_img(img_src, output_path, text: str):
    """图片扩大，加框，加文字，保存图片

    Args:
        img_src: 图片路径
        output_path: 保存路径
        text: 文字
    """
    # 加载商品图
    img = load_img(img_src)
    # 加载图层
    layer_img = load_img("layer.png")
    # 获取背景色
    background_color = get_background_color(img)
    if background_color is None:
        # 如果背景色为空，则使用黑色
        background_color = (0, 0, 0, 255)
    # 调整图片为正方形，填充背景色
    square_img = resize_to_square_with_black_bg(img, 800, background_color)
    # 图片加框
    layer_img = no_conversion_overlay(square_img, layer_img)
    # 添加文字
    res_img = add_text_auto_fit_layered(
        layer_img,
        text,
        region=(350, 700, 790, 790),
        max_font_size=40,
        min_font_size=12,
    )
    # 保存图片
    save_img(res_img, output_path)


if __name__ == "__main__":
    process_img("download/801011.jpg", "test_img.png")
